home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / 031-040 / amok32 / ringbuffers / ringbuffers.mod < prev    next >
Text File  |  1993-11-04  |  6KB  |  207 lines

  1. (**********************************************************************
  2.  
  3.     :Program.    RingBuffers.mod
  4.     :Contents.   Generic data type: ring buffer
  5.     :Author.     Nicolas Benezan [bne]
  6.     :Address.    Postwiesenstr. 2, D7000 Stuttgart 60
  7.     :Phone.      711/333679
  8.     :Copyright.  Public Domain
  9.     :Language.   Modula-2
  10.     :Translator. M2Amiga A+L V3.27d
  11.     :Imports.    TaskMemory [bne]
  12.     :History.    V1.0 [bne] 31.Dec.1989
  13.     :History.    V1.1 [bne] 01.Jan.1990 (bug fixes)
  14.     :History.    V1.2 [bne] 10.Jan.1990 (+ multitasking)
  15.  
  16. **********************************************************************)
  17.  
  18. IMPLEMENTATION MODULE RingBuffers;
  19.  
  20. FROM Arts        IMPORT Assert;
  21. FROM Exec        IMPORT MsgPort, MsgPortPtr, PutMsg, GetMsg, SetSignal, Node,
  22.                         MsgPortAction, NodeType, TaskPtr;
  23. FROM ExecSupport IMPORT NewList;
  24. FROM SYSTEM      IMPORT ADDRESS, ADR, BYTE, LONGSET, SETREG;
  25. FROM TaskMemory  IMPORT Allocate, Deallocate;
  26.  
  27. TYPE
  28.   RingBuffer = POINTER TO RingBufferRec;
  29.   RingBufferRec = RECORD
  30.     fullQueue : MsgPort;
  31.     emptyQueue: MsgPort;
  32.     link: RingBufferBlock;
  33.   END;
  34.   RingBufferBlock = POINTER TO RingBufferBlockRec;
  35.   RingBufferBlockRec = RECORD
  36.     node: Node;
  37.     link: RingBufferBlock;
  38.     data: BYTE; (* Dummy *)
  39.   END;
  40.  
  41. PROCEDURE InitMsgPort (VAR Port: MsgPort;
  42.                            SigBit: INTEGER;
  43.                            SigTask: TaskPtr);
  44.   BEGIN
  45.     WITH Port DO
  46.       node.type:= msgPort;
  47.       node.name:= NIL;
  48.       node.pri := 0;
  49.       flags    := signal;
  50.       sigBit   := SigBit;
  51.       sigTask  := SigTask;
  52.       NewList (ADR (msgList));
  53.     END;
  54.   END InitMsgPort;
  55.  
  56. PROCEDURE CreateRingBuffer (VAR Buffer: RingBuffer;
  57.                                 BlockSize: LONGINT;
  58.                                 NumBlocks: CARDINAL;
  59.                                 FullSigTask: TaskPtr;
  60.                                 FullSignal: INTEGER;
  61.                                 EmptySigTask: TaskPtr;
  62.                                 EmptySignal: INTEGER): BOOLEAN;
  63.   VAR
  64.     BlockPtr: RingBufferBlock;
  65.   BEGIN
  66.     Assert (NumBlocks > 0, ADR ("RingBuffers: NumBlocks = 0"));
  67.     RingBuffersAllocProc (Buffer, SIZE (RingBufferRec));
  68.     IF Buffer # NIL THEN
  69.       WITH Buffer^ DO
  70.         link:= NIL;
  71.         InitMsgPort (fullQueue, FullSignal, FullSigTask);
  72.         InitMsgPort (emptyQueue, EmptySignal, EmptySigTask);
  73.         REPEAT
  74.           RingBuffersAllocProc (BlockPtr, SIZE (RingBufferBlockRec) +
  75.                                 BlockSize - 1);
  76.           IF BlockPtr = NIL THEN
  77.             DiscardRingBuffer (Buffer);
  78.             RETURN FALSE
  79.           END;
  80.           BlockPtr^.link:= Buffer^.link;
  81.           Buffer^.link:= BlockPtr;
  82.           PutMsg (ADR (emptyQueue), BlockPtr);
  83.           DEC (NumBlocks);
  84.         UNTIL NumBlocks = 0;
  85.         RETURN TRUE
  86.       END;
  87.       RingBuffersDeallocProc (Buffer);
  88.     END;
  89.     RETURN FALSE
  90.   END CreateRingBuffer;
  91.  
  92. PROCEDURE ErrorNoBuffer;
  93.   BEGIN
  94.     Assert (FALSE, ADR ("RingBuffers: undefined buffer"));
  95.   END ErrorNoBuffer;
  96.  
  97. PROCEDURE ErrorNoBlock;
  98.   BEGIN
  99.     Assert (FALSE, ADR ("RingBuffers: undefined block"));
  100.   END ErrorNoBlock;
  101.  
  102. PROCEDURE DiscardRingBuffer (VAR Buffer: RingBuffer);
  103.   VAR
  104.     BlockPtr: RingBufferBlock;
  105.   BEGIN
  106.     IF Buffer = NIL THEN
  107.       ErrorNoBuffer;
  108.     END;
  109.     WITH Buffer^ DO
  110.       WHILE link # NIL DO
  111.         BlockPtr:= link;
  112.         link:= BlockPtr^.link;
  113.         RingBuffersDeallocProc (BlockPtr);
  114.       END;
  115.     END;
  116.     RingBuffersDeallocProc (Buffer);
  117.     Buffer:= NIL;
  118.   END DiscardRingBuffer;
  119.  
  120. PROCEDURE GetBlock (    Queue: MsgPortPtr;
  121.                     VAR Block: RingBufferBlock;
  122.                     VAR DataPtr: ADDRESS): BOOLEAN;
  123.   BEGIN
  124.     SETREG (0, SetSignal (LONGSET{}, LONGSET{Queue^.sigBit}));
  125.     Block:= GetMsg (Queue);
  126.     IF Block # NIL THEN
  127.       DataPtr:= ADR (Block^.data);
  128.       RETURN TRUE
  129.     END;
  130.     DataPtr:= NIL;
  131.     RETURN FALSE
  132.   END GetBlock;
  133.  
  134. PROCEDURE GetFullBlock (    Buffer: RingBuffer;
  135.                         VAR Block: RingBufferBlock;
  136.                         VAR DataPtr: ADDRESS): BOOLEAN;
  137.   BEGIN
  138.     IF Buffer = NIL THEN
  139.       ErrorNoBuffer;
  140.     END;
  141.     RETURN GetBlock (ADR (Buffer^.fullQueue), Block, DataPtr);
  142.   END GetFullBlock;
  143.  
  144. PROCEDURE GetEmptyBlock (    Buffer: RingBuffer;
  145.                          VAR Block: RingBufferBlock;
  146.                          VAR DataPtr: ADDRESS): BOOLEAN;
  147.   BEGIN
  148.     IF Buffer = NIL THEN
  149.       ErrorNoBuffer;
  150.     END;
  151.     RETURN GetBlock (ADR (Buffer^.emptyQueue), Block, DataPtr);
  152.   END GetEmptyBlock;
  153.  
  154. PROCEDURE PutFullBlock (    Buffer: RingBuffer;
  155.                         VAR Block: RingBufferBlock);
  156.   BEGIN
  157.     IF Buffer = NIL THEN
  158.       ErrorNoBuffer;
  159.     END;
  160.     IF Block = NIL THEN
  161.       ErrorNoBlock;
  162.     END;
  163.     PutMsg (ADR (Buffer^.fullQueue), Block);
  164.     Block:= NIL;
  165.   END PutFullBlock;
  166.  
  167. PROCEDURE PutEmptyBlock (    Buffer: RingBuffer;
  168.                          VAR Block: RingBufferBlock);
  169.   BEGIN
  170.     IF Buffer = NIL THEN
  171.       ErrorNoBuffer;
  172.     END;
  173.     IF Block = NIL THEN
  174.       ErrorNoBlock;
  175.     END;
  176.     PutMsg (ADR (Buffer^.emptyQueue), Block);
  177.     Block:= NIL;
  178.   END PutEmptyBlock;
  179.  
  180. PROCEDURE AllBlocksFull (Buffer: RingBuffer): BOOLEAN;
  181.   BEGIN
  182.     IF Buffer = NIL THEN
  183.       ErrorNoBuffer;
  184.     END;
  185.     WITH Buffer^.emptyQueue DO
  186.       SETREG (0, SetSignal (LONGSET{}, LONGSET{sigBit}));
  187.       RETURN msgList.head^.succ = NIL
  188.     END;
  189.   END AllBlocksFull;
  190.  
  191. PROCEDURE AllBlocksEmpty (Buffer: RingBuffer): BOOLEAN;
  192.   BEGIN
  193.     IF Buffer = NIL THEN
  194.       ErrorNoBuffer;
  195.     END;
  196.     WITH Buffer^.fullQueue DO
  197.       SETREG (0, SetSignal (LONGSET{}, LONGSET{sigBit}));
  198.       RETURN msgList.head^.succ = NIL
  199.     END;
  200.   END AllBlocksEmpty;
  201.  
  202. BEGIN
  203.   RingBuffersAllocProc:= Allocate;
  204.   RingBuffersDeallocProc:= Deallocate;
  205. END RingBuffers.
  206.  
  207.